home *** CD-ROM | disk | FTP | other *** search
- /*
-
- sbinder.cpp
- 10-25-91
- Streamable Binder: Loose Data Binder v 1.5
-
- Copyright 1991
- John W. Small
- All rights reserved
-
- PSW / Power SoftWare
- P.O. Box 10072
- McLean, Virginia 22102 8072 USA
-
- John Small
- Voice: (703) 759-3838
- CIS: 73757,2233
-
- */
-
-
- #include <string.h>
- #include "sbinder.hpp"
-
-
- void Streamable::lserror(const char *msg, unsigned id)
- {
- if (streamDebug)
- cerr << endl
- << "Class id: " << setw(6) << id
- << " stream error - "
- << msg << endl;
- }
-
- void Streamable::serror(const char *msg)
- {
- if (streamDebug)
- cerr << endl
- <<"Class id: " << setw(6) << id
- << " &instance: "
- << (void *) this << endl
- << "Stream error - "
- << msg << endl;
- }
-
- void Streamable::swarn(const char *msg)
- {
- if (streamDebug)
- cerr << endl
- << "Class id: " << setw(6) << id
- << " &instance: "
- << (void *) this << endl
- << "Stream warning - "
- << msg << endl;
- }
-
-
- #pragma argsused
- StreamablE Streamable::load(istream& is,
- StreamablE InstancE)
- { return InstancE; }
-
- int Streamable::refDebug = 0;
- int Streamable::streamDebug = 0;
- char Streamable::memberTermChar = '\n';
-
- #pragma argsused
- Streamable::Streamable(StreamableClassRegistry& dummy,
- unsigned id)
- {
- parenT = voiD0;
- this->id = id;
- refCount = streamCount = 0;
- streamPos = 0L;
- }
-
- void Streamable::registerClass(unsigned id,
- StreamablE (*loader)(istream& is,
- StreamablE InstancE))
- {
- SCRegistry.registerClass(id,loader);
- }
-
- unsigned Streamable::restream()
- {
- unsigned underFlow = (streamPos?
- refCount - streamCount : 0);
-
- streamCount = 0;
- streamPos = 0L;
- if (underFlow)
- swarn("restream: streamed less than "
- "referenced");
- return underFlow;
- }
-
- unsigned Streamable::unlink(voiD P)
- {
- if (refDebug)
- if (refCount)
- cerr << endl
- << "Class id: " << setw(6) << id
- << " &instance: "
- << (void *) this << endl
- << "Unlinking, starting refCount: "
- << refCount << endl;
- else
- cerr << endl
- << "Class id: " << setw(6) << id
- << " &instance: "
- << (void *) this << endl
- << "unlink() underflow" << endl;
- if (refCount)
- --refCount;
- if (parenT == P || !refCount)
- parenT = voiD0;
- return refCount;
- }
-
- StreamablE Streamable::link(voiD P)
- {
- if (refCount >= UINT_MAX) {
- if (refDebug)
- cerr << endl
- << "Class id: " << setw(6) << id
- << " &instance: "
- << (void *) this << endl
- << "link() overflow" << endl;
- return StreamablE0;
- }
- refCount++;
- if (!parenT && P)
- parenT = P;
- if (refDebug)
- cerr << endl
- << "Class id: " << setw(6) << id
- << " &instance: "
- << (void *) this << endl
- << "Adding link, new refCount: "
- << refCount << endl;
- return this;
- }
-
- ostream& endm(ostream& os)
- {
- return os << Streamable::memberTermChar
- << flush;
- }
-
- istream& nextm(istream& is)
- {
- is.get();
- return is;
- }
-
- int SBinder::Dfree(voiD D)
- {
- if (D) {
- if (!((StreamablE)D)->RefCount())
- delete (StreamablE) D;
- return 1;
- }
- return 0;
- }
-
- int SBinder::Dattach(voiD D)
- {
- return ((((StreamablE)D)->link(this))? 1 : 0);
- }
-
- void SBinder::Ddetach(voiD D)
- {
- ((StreamablE)D)->unlink(this);
- }
-
- ostream& SBinder::store(ostream& os)
- {
- unsigned i;
-
- os << maxNodes << endm << limit << endm
- << delta << endm << nodes << endm
- << curNode << endm << flags << endm
- << FncPtrToID((GenericFnC)comparE) << endm;
- if (!os)
- serror("unable to store Streamable Binder");
- else for (i = 0; i < nodes; i++)
- Dstore(os,atGet(i));
- return os;
- }
-
- StreamablE SBinder::load(istream& is, StreamablE InstancE)
- {
- unsigned i, maxNodes, limit, delta, nodes, curNode;
- unsigned flags;
- unsigned comparEID;
-
- is >> maxNodes >> nextm >> limit >> nextm
- >> delta >> nextm >> nodes >> nextm
- >> curNode >> nextm >> flags >> nextm
- >> comparEID >> nextm;
- if (!is) {
- lserror("unable to load Streamable Binder "
- "header data",
- ID_CLASS);
- return StreamablE0;
- }
- flags |= BDR_OK_FREE; // reloaded nodes are dynamic!
- if (!InstancE)
- if ((InstancE = (StreamablE)
- new SBinder(UNIQUE_STREAMABLE))
- == StreamablE0) {
- lserror("unable to construct "
- "Streamable Binder for "
- "loading",ID_CLASS);
- return StreamablE0;
- }
- ((SBindeR)InstancE)->construct(flags,maxNodes,
- limit,delta);
- StreamablE D;
- for (i = 0; i < nodes; i++)
- ((SBindeR)InstancE)->insQ(
- ((SBindeR)InstancE)->Dload(is));
- ((SBindeR)InstancE)->setCurNode(curNode);
- ((SBindeR)InstancE)->setComparE((BDRcomparE)
- IDtoFncPtr(comparEID));
- return InstancE;
- }
-
- void SBinder::Dstore(ostream& os, voiD D)
- { os << (StreamablE) D; }
-
- voiD SBinder::Dload(istream& is)
- {
- StreamablE InstancE = StreamablE0;
-
- is >> InstancE;
- return (voiD) InstancE;
- }
-
- unsigned SBinder::restream()
- {
- unsigned result = Streamable::restream();
- for (unsigned i = 0; i < nodes; i++)
- ((StreamablE)atGet(i))->restream();
- return result;
- }
-
- SBinder::~SBinder()
- {
- if (Flags(BDR_OK_FREE))
- allFree();
- else
- allDel();
- }
-
-
- StreamableClassRegistry SCRegistry;
-
- int StreamableClassRegistry::debug = 0;
-
- void StreamableClassRegistry::error(char *msg, unsigned id,
- StreamablE InstancE)
- {
- if (debug)
- cerr << endl
- << "Class id: " << setw(6) << id
- << " &instance: "
- << (void *) InstancE << endl
- << "ClassRegistry error - "
- << msg << endl;
- }
-
- void StreamableClassRegistry::warn(char *msg, unsigned id,
- StreamablE InstancE)
- {
- if (debug)
- cerr << endl
- << "Class id: " << setw(6) << id
- << " &instance: "
- << (void *) InstancE << endl
- << "ClassRegistry warning - "
- << msg << endl;
- }
-
- unsigned StreamableClassRegistry::restream()
- {
-
- unsigned underFlow = InstanceLinks.Nodes();
- IHRecorD R;
-
- for (unsigned i = 0; i < underFlow; i++) {
- R = (IHRecorD) InstanceLinks.atGet(i);
- warn("Restream: holding pen under-linked",
- R->InstancE->id,R->InstancE);
- }
- InstanceLinks.allFree();
- return underFlow;
- }
-
- void StreamableClassRegistry::registerClass(unsigned id,
- StreamablE (*loader) (istream& is,
- StreamablE InstancE))
- {
- unsigned i;
-
- for (i = 0; i < ClassRecords.Nodes(); i++)
- if (((SCRecorD)ClassRecords[i])->id
- == id)
- break;
- if (i < ClassRecords.Nodes())
- if (((SCRecorD)ClassRecords[i])->load
- == loader) {
- warn("multiple registration of"
- " loader",id);
- return;
- }
- else {
- error("id conflict: ",id);
- return;
- }
- SCRecorD R = new StreamableClassRecord(id,loader);
- if (!R)
- error("class record memory exhausted",
- id);
- else if (!ClassRecords.insQ(R)) {
- error("class record can't be queued",
- id);
- delete R;
- }
- }
-
- void StreamableClassRegistry::forgetClasses()
- {
- ClassRecords.allFree();
- InstanceLinks.allFree();
- }
-
- istream& StreamableClassRegistry::get(istream& is,
- StreamablE& InstancE)
- {
- unsigned id, refCount, i;
- long streamPos;
- IHRecorD R;
-
- InstancE = StreamablE0;
- if (!(is >> id >> nextm)) {
- error("unable to read id");
- return is;
- }
- if (id == ID_StreamableRef) {
- // link to previously loaded Instance
- if (!(is >> streamPos >> nextm)) {
- error("unable to read streamPos");
- return is;
- }
- for (i = 0; i < InstanceLinks.Nodes(); i++)
- if ((R = (IHRecorD)InstanceLinks[i])
- ->streamPos == streamPos) {
- // found saved instance!
- InstancE = R->InstancE;
- if (R->refCount <= ++R->streamCount)
- // discard when done!
- InstanceLinks.atDel(i);
- break;
- }
- if (!InstancE)
- error("unable to establish link to"
- " previously loaded class",
- id);
- }
- else { // load instance
- streamPos = is.tellg();
- if (!(is >> refCount >> nextm)) {
- error("unable to read refCount",id);
- return is;
- }
- for (i = 0; i < ClassRecords.Nodes(); i++)
- if (((SCRecorD)ClassRecords[i])->id
- == id)
- break;
- if (i >= ClassRecords.Nodes()) {
- error("attempted load of unknown "
- "class",id);
- return is;
- }
- if ((InstancE = (*((SCRecorD)
- ClassRecords[i])->load)
- (is,StreamablE0)) == StreamablE0)
- {
- error("unable to load instance",id);
- return is;
- }
- if (refCount > 1) {
- // 1st of many save in holding pen
- R = new InstanceHoldingRecord
- (InstancE,refCount,streamPos);
- if (!R)
- error("class holding record"
- " memory exhausted,"
- " id: ",id,InstancE);
- else if (!InstanceLinks.insQ(R)) {
- error("unable to hold "
- "instance for "
- "multiple links ",
- id,InstancE);
- delete R;
- }
- }
- }
- return is;
- }
-
- ostream& StreamableClassRegistry::put(ostream& os,
- StreamablE InstancE)
- {
- unsigned id, i;
- long tpos;
-
- if (!InstancE)
- return os;
- id = InstancE->id;
- for (i = 0; i < ClassRecords.Nodes(); i++)
- if (((SCRecorD)ClassRecords[i])->id == id)
- break;
- if (i >= ClassRecords.Nodes()) {
- error("attempted store of unknown class: ",
- id);
- }
- else if (InstancE->refCount <= InstancE->streamCount)
- error("more attempting stores than links",
- id,InstancE);
- else {
- InstancE->streamCount++;
- if (InstancE->streamPos) {
- // already stored!
- if (!(os << ID_StreamableRef << endm
- << InstancE->streamPos
- << endm))
- error("unable to store "
- "multiple reference",
- id,InstancE);
- }
- else if (!(os << id << endm))
- error("unable to store id",
- id,InstancE);
- else {
- InstancE->streamPos = os.tellp();
- if (!(os << InstancE->refCount
- << endm))
- error("unable to store "
- "refCount ",id,
- InstancE);
- else
- InstancE->store(os);
- }
- }
- return os << flush;
- }
-
-
- StreamableFncPtrRegistry SFPRegistry;
-
- int StreamableFncPtrRegistry::debug;
-
- void StreamableFncPtrRegistry::error(char *msg, unsigned id)
- {
- if (debug)
- cerr << "FncPtrRegistry error - "
- << msg << id << endl;
- }
-
- void StreamableFncPtrRegistry::warn(char *msg, unsigned id)
- {
- if (debug)
- cerr << "FncPtrRegistry warning - "
- << msg << id << endl;
-
- }
-
- void StreamableFncPtrRegistry::registerFunction(unsigned id,
- GenericFnC fnC)
- {
- unsigned i;
-
- for (i = 0; i < FncPtrRecords.Nodes(); i++)
- if (((SFPRecorD)FncPtrRecords[i])->id == id)
- break;
- if (i < FncPtrRecords.Nodes())
- if (((SFPRecorD)FncPtrRecords[i])->fnC
- == fnC)
- {
- warn("attempted multiple"
- " registration"
- " of function pointer: ",
- id);
- return;
- }
- else {
- error("id conflict: ",id);
- return;
- }
- SFPRecorD R = new StreamableFncPtrRecord(id,fnC);
- if (!R)
- error("fncPtr memory exhausted, id: ",id);
- else if (!FncPtrRecords.insQ(R)) {
- error("fncPtr record can't be queued, id: ",
- id);
- delete R;
- }
- }
-
-
- GenericFnC StreamableFncPtrRegistry::FnC(unsigned id)
- {
- unsigned i;
-
- for (i = 0; i < FncPtrRecords.Nodes(); i++)
- if (((SFPRecorD)FncPtrRecords[i])->id == id)
- break;
- if (i >= FncPtrRecords.Nodes()) {
- error("unknown fncPtr: ",id);
- return GenericFnC0;
- }
- else
- return ((SFPRecorD)FncPtrRecords[i])->fnC;
- }
-
- unsigned StreamableFncPtrRegistry::ID(GenericFnC fnC)
- {
- unsigned i;
-
- for (i = 0; i < FncPtrRecords.Nodes(); i++)
- if (((SFPRecorD)FncPtrRecords[i])->fnC
- == fnC)
- break;
- if (i >= FncPtrRecords.Nodes()) {
- error("unknown fncPtr: ",
- ID_UnknownGenericFnC);
- return ID_UnknownGenericFnC;
- }
- else
- return ((SFPRecorD)FncPtrRecords[i])->id;
- }
-
-